package club.jdiy.admin.context;

import club.jdiy.core.cache.CacheClient;
import club.jdiy.core.cache.NoneClient;
import club.jdiy.core.properties.JDiyProperties;
import club.jdiy.core.AppContext;
import club.jdiy.utils.CookieUtils;
import club.jdiy.utils.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import java.util.*;

public class ClusterSession implements HttpSession {
    private static final String prefix = "@SESSION_";
    private final HttpServletResponse response;
    private final HttpServletRequest request;
    private final HttpSession oldSession;

    ClusterSession(HttpServletRequest request, HttpServletResponse response, HttpSession oldSession) {
        this.request = request;
        this.response = response;
        this.oldSession = oldSession;
    }

    @Override
    @SuppressWarnings("ALL")
    public String getId() {
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        JDiyProperties conf = ctx.getBean(JDiyProperties.class);
        String sessId = CookieUtils.getCookie(request, conf.getAppid() + "_sessId");
        if (StringUtils.isEmpty(sessId)) {
            sessId = String.valueOf(UUID.randomUUID()).replaceAll("-", "");
            CookieUtils.setCookie(request, response, conf.getAppid() + "_sessId", sessId, 5 * 365 * 24 * 60 * 60); //----此cookie有效期可以无限长（若不清cookie，则5年不过期）
        }
        return sessId;
    }

    @Override
    @SuppressWarnings("ALL")
    public void invalidate() {
        String session_key = prefix + getId();
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        CacheClient cacheClient = ctx.getBean(AppContext.class).getCacheClient();
        if (cacheClient instanceof NoneClient) oldSession.invalidate();
        else cacheClient.delete(session_key);
    }

    @Override
    @SuppressWarnings("ALL")
    public Object getAttribute(String s) {
        String session_key = prefix + getId();
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        CacheClient cacheClient = ctx.getBean(AppContext.class).getCacheClient();
        if (cacheClient instanceof NoneClient) return oldSession.getAttribute(s);
        Map<String, Object> sessionMap = (Map<String, Object>) cacheClient.get(session_key);
        return sessionMap == null ? null : sessionMap.get(s);
    }

    @Override
    @SuppressWarnings("ALL")
    public Enumeration<String> getAttributeNames() {
        String session_key = prefix + getId();
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        CacheClient cacheClient = ctx.getBean(AppContext.class).getCacheClient();
        if (cacheClient instanceof NoneClient) return oldSession.getAttributeNames();
        Map<String, Object> sessionMap = (Map<String, Object>) cacheClient.get(session_key);
        return sessionMap == null ? null : Collections.enumeration(sessionMap.keySet());
    }

    @Override
    @SuppressWarnings("ALL")
    public void setAttribute(String s, Object o) {
        String session_key = prefix + getId();
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        CacheClient cacheClient = ctx.getBean(AppContext.class).getCacheClient();
        if (cacheClient instanceof NoneClient) {
            oldSession.setAttribute(s, o);
            return;
        }
        HashMap<String, Object> sessionMap = cacheClient.get(session_key);
        if (sessionMap == null) sessionMap = new HashMap<>();
        sessionMap.put(s, o);
        cacheClient.set(session_key, sessionMap, 60 * 60 * 24 * 30);

        sessionMap = cacheClient.get(session_key);
    }

    @Override
    @SuppressWarnings("ALL")
    public void removeAttribute(String s) {
        String session_key = prefix + getId();
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        CacheClient cacheClient = ctx.getBean(AppContext.class).getCacheClient();
        if (cacheClient instanceof NoneClient) {
            oldSession.removeAttribute(s);
            return;
        }
        HashMap<String, Object> sessionMap = cacheClient.get(session_key);
        if (sessionMap != null) {
            sessionMap.remove(s);
            if (sessionMap.isEmpty()) cacheClient.delete(session_key);
            else
                cacheClient.set(session_key, sessionMap, 60 * 60 * 24 * 30);
        }
    }

    //-------------------------------

    @Override
    public ServletContext getServletContext() {
        return request.getServletContext();
    }

    @Override
    public long getCreationTime() {
        return 0;
    }

    @Override
    public long getLastAccessedTime() {
        return 0;
    }

    @Override
    public void setMaxInactiveInterval(int i) {

    }

    @Override
    public int getMaxInactiveInterval() {
        return 0;
    }

    @Override
    public boolean isNew() {
        return false;
    }

    @Override
    @Deprecated
    public HttpSessionContext getSessionContext() {
        return null;
    }

    @Override
    @Deprecated
    public Object getValue(String s) {
        return getAttribute(s);
    }

    @Override
    @Deprecated
    public String[] getValueNames() {
        return new String[0];
    }

    @Override
    @Deprecated
    public void putValue(String s, Object o) {
        setAttribute(s, o);
    }

    @Override
    @Deprecated
    public void removeValue(String s) {
        removeAttribute(s);
    }
}
